
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       battery_monitor_analog.c
  * @author     baiyang
  * @date       2022-10-27
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include "battery_monitor_analog.h"

#include <common/time/gp_time.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/
static void read(battery_monitor_backend_t battmonitor_backend);
static bool has_current(battery_monitor_backend_t battmonitor_backend);
static bool has_consumed_energy(battery_monitor_backend_t battmonitor_backend);
/*----------------------------------variable----------------------------------*/
struct battery_monitor_backend_ops battmonitor_analog_ops = {.battery_monitor_backend_destructor = NULL, 
                                                             .init = NULL,
                                                             .read = read,
                                                             .has_time_remaining = NULL,
                                                             .has_consumed_energy = has_consumed_energy,
                                                             .has_current = has_current,
                                                             .has_cell_voltages = NULL,
                                                             .has_temperature = NULL,
                                                             .capacity_remaining_pct = NULL,
                                                             .get_cycle_count = NULL,
                                                             .update_failsafes = NULL,
                                                             .reset_remaining = NULL,
                                                             .get_mavlink_fault_bitmask = NULL};

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
void battery_monitor_analog_ctor(battery_monitor_analog_t battmonitor_analog, battery_monitor_state_t mon_state, battery_monitor_params_t params)
{
    rt_memset(battmonitor_analog, 0, sizeof(struct battery_monitor_analog));

    battmonitor_backend_ctor(&battmonitor_analog->backend, &battmonitor_analog_ops, mon_state, params);

    battmonitor_analog->_volt_pin_analog_source = analogin_channel(battmonitor_analog->backend._params->_volt_pin);
    battmonitor_analog->_curr_pin_analog_source = analogin_channel(battmonitor_analog->backend._params->_curr_pin);
}

battery_monitor_backend_t battery_monitor_analog_probe(battery_monitor_state_t mon_state, battery_monitor_params_t params)
{
    if (!mon_state || !params) {
        return NULL;
    }

    battery_monitor_analog_t battmonitor_analog = (battery_monitor_analog_t)rt_malloc(sizeof(struct battery_monitor_analog));

    if (!battmonitor_analog) {
        return NULL;
    }

    battery_monitor_analog_ctor(battmonitor_analog, mon_state, params);

    return (battery_monitor_backend_t)battmonitor_analog;
}

// read - read the voltage and current
static void read(battery_monitor_backend_t battmonitor_backend)
{
    battery_monitor_analog_t battmonitor_analog = (battery_monitor_analog_t)battmonitor_backend;

    // this copes with changing the pin at runtime
    battmonitor_backend->_state->healthy = analogsource_set_pin(battmonitor_analog->_volt_pin_analog_source , battmonitor_backend->_params->_volt_pin);

    // get voltage
    battmonitor_backend->_state->voltage = (analogsource_voltage_average(battmonitor_analog->_volt_pin_analog_source) - battmonitor_backend->_params->_volt_offset) * battmonitor_backend->_params->_volt_multiplier;

    // read current
    if (battmonitor_backend_has_current(battmonitor_backend)) {
        // calculate time since last current read
        const uint32_t tnow = time_micros();
        const uint32_t dt_us = tnow - battmonitor_backend->_state->last_time_micros;

        // this copes with changing the pin at runtime
        battmonitor_backend->_state->healthy &= analogsource_set_pin(battmonitor_analog->_curr_pin_analog_source, battmonitor_backend->_params->_curr_pin);

        // read current
        battmonitor_backend->_state->current_amps = (analogsource_voltage_average(battmonitor_analog->_curr_pin_analog_source) - battmonitor_backend->_params->_curr_amp_offset) * battmonitor_backend->_params->_curr_amp_per_volt;

        battmonitor_backend_update_consumed(battmonitor_backend->_state, dt_us);

        // record time
        battmonitor_backend->_state->last_time_micros = tnow;
    }
}

/// return true if battery provides current info
static bool has_current(battery_monitor_backend_t battmonitor_backend)
{
    return ((enum BattMonitorType)battmonitor_backend->_params->_type == BATT_MONITOR_ANALOG_VOLTAGE_AND_CURRENT);
}

/// returns true if battery monitor provides consumed energy info
static bool has_consumed_energy(battery_monitor_backend_t battmonitor_backend)
{
    return battmonitor_backend_has_current(battmonitor_backend);
}

/*------------------------------------test------------------------------------*/


